Map = {}
Map.new = function(width, height)
	effect = love.graphics.newPixelEffect [[
		extern number camera_x;
		extern number camera_y;
		
		number dist_x;
		number dist_y;
		number modifier_x;
		number modifier_y;
		number modifier;
		
        vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 pixel_coords) {
		
			dist_x = min(pixel_coords.x + camera_x, 3000 - pixel_coords.x - camera_x);
			dist_y = min(pixel_coords.y + camera_y, 2000 - pixel_coords.y - camera_y);
			
			modifier_x = min(50, dist_x) / 50;
			modifier_y = min(50, dist_y) / 50;
			modifier = modifier_x * modifier_y;
		
			vec4 pixel = Texel(texture, texture_coords);

			pixel.r = max(0, min(1.0, pixel.r * (0.2 + modifier * 0.8)));
			pixel.g = max(0, min(1.0, pixel.g * (0.2 + modifier * 0.8)));
			pixel.b = max(0, min(1.0, pixel.b * (0.2 + modifier * 0.8)));
			return  pixel;
		}
    ]]
	
	local self = {}
	local width = width
	local height = height
	local texture = love.graphics.newImage("img/grid2.png")
	local quad = love.graphics.newQuad(0, 0, width, height, texture:getWidth(), texture:getHeight())
	texture:setWrap("repeat", "repeat")
	
	
	self.getWidth = function() return width end
	self.getHeight = function() return height end
	self.getTexture = function() return texture end
	self.getQuad = function() return quad end
	
	function self:draw()
		effect:send("camera_x", camera.getX())
		effect:send("camera_y", camera.getY())
		--love.graphics.setPixelEffect(effect)
		love.graphics.drawq(texture, quad, 0, 0, 0, 1, 1, camera.getX(), camera.getY())
		--love.graphics.setPixelEffect()
	end
	
	setmetatable(self, Map)
	return self
end

Camera = {}
Camera.new = function(x, y)
	local self = {}
	local x = x or 0
	local y = y or 0
	
	self.getX = function() return round(x) end
	self.getY = function() return round(y) end
	
	self.setX = function(val) x = val end
	self.setY = function(val) y = val end
	
	function self:update(dt)
		if player.getX() > love.graphics.getWidth() / 2 + x then x = x + math.max(0, player.getVelX()) * dt elseif
		player.getX() < love.graphics.getWidth() / 2 + x then x = x + math.min(0, player.getVelX()) * dt end
		if player.getY() > love.graphics.getHeight() / 2 + y then y = y + math.max(0, player.getVelY()) * dt elseif
		player.getY() < love.graphics.getHeight() / 2 + y then y = y + math.min(0, player.getVelY()) * dt end
		
		--x = clamp(x, 0, map.getWidth() - love.graphics.getWidth())
		--y = clamp(y, 0, map.getHeight() - love.graphics.getHeight())
	end
	
	setmetatable(self, Camera)
	return self
end

Player = {}
Player.new = function(x, y, width, height)
	local self = {}
	local width = width
	local height = height
	local x = x or 0
	local y = y or 0
	local x2 = x
	local y2 = y
	local velX = 0
	local velY = 0
	local speed = 200
	local angle = 0
	local angle2 = 0
	local image = love.graphics.newImage("img/arrow.png")
	
	self.getWidth = function() return width end
	self.getHeight = function() return height end
	self.getX = function() return x end
	self.getY = function() return y end
	self.getVelX = function() return velX end
	self.getVelY = function() return velY end
	self.getSpeed = function() return speed end
	self.getAng = function() return angle end
	self.getImage = function() return image end
	
	self.setX = function(val) x = val end
	self.setY = function(val) y = val end
	self.setVelX = function(val) velX = val end
	self.setVelY = function(val) velY = val end
	self.setSpeed = function(val) speed = val end
	self.setAng = function(val) angle = val end
	
	function self:fire()
		Bullet.new(x, y, speed + 300, angle)
	end
	
	function self:update(dt)
		if love.mouse.getX() < (x - camera.getX()) then
			angle2 = math.atan(((love.mouse.getY() + camera.getY()) - y) / (love.mouse.getX() +	camera.getX() - x)) + math.pi
		else
			angle2 = math.atan(((love.mouse.getY() + camera.getY()) - y) / (love.mouse.getX() + camera.getX() - x))
		end
		
		velX = speed * math.cos(angle)
		velY = speed * math.sin(angle)
		x = x + velX * dt
		y = y + velY * dt
		angle = angle2
	end
	
	function self:draw()
		love.graphics.draw(image, round(x - camera.getX()), round(y - camera.getY()), angle, 1, 1, image:getWidth() / 2, image:getHeight() / 2)
	end
	
	setmetatable(self, Player)
	return self
end

Bullet = {}
Bullet.new = function(x, y, speed, angle)
	local self = {}
	local x = x
	local y = y
	local velX = speed * math.cos(angle)
	local velY = speed * math.sin(angle)
	local image = love.graphics.newImage("img/bullet.png")
	
	self.getX = function() return x end
	self.getY = function() return y end
	self.getVelX = function() return velX end
	self.getVelY = function() return velY end
	self.getImage = function() return image end
	
	self.setX = function(val) x = val end
	self.setY = function(val) y = val end
	self.setVelX = function(val) velX = val end
	self.setVelY = function(val) velY = val end
	
	function self:update(dt)
		x = x + velX * dt
		y = y + velY * dt
	end
	
	function self:draw()
		love.graphics.draw(image, round(x - camera.getX()), round(y - camera.getY()), 0, 1, 1, 4, 4)
	end
	
	function self:delete(key)
		table.remove(bullets, key)
		anim = Animation.new(x, y, "img/explosion.png", 64, 64, 0.05, math.random(0, math.pi * 2))
		print("DELETED BULLET")
	end
	
	table.insert(bullets, self)
	
	setmetatable(self, Bullet)
	return self
end

Animation = {}
Animation.new = function(x, y, image, width, height, timestep, angle)
	local self = {}
	local x = round(x)
	local y = round(y)
	local image = love.graphics.newImage(image)
	local g = anim8.newGrid(width, height, image:getWidth(), image:getHeight())
	local animation = anim8.newAnimation("once", g('1-4,1', '1-4,2', '1-4,3', '1-4,4'), timestep)
	local angle = angle
	
	self.getX = function() return x end
	self.getY = function() return y end
	
	self.setX = function(val) x = val end
	self.setY = function(val) y = val end
	
	function self:currentFrame()
		return animation:currentFrame()
	end
	
	function self:frameCount()
		return animation:frameCount()
	end
	
	function self:update(dt)
		animation:update(dt)
	end
	
	function self:draw()
		animation:draw(image, x - camera.getX(), y - camera.getY(), angle, 1, 1, width / 2, height / 2)
	end
	
	table.insert(animations, self)
	
	setmetatable(self, Animation)
	return self
end